#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>

#define MAX_EVENTS 100
#define BUFFER_SIZE 1024

// 设置文件描述符为非阻塞模式
// 针对客户端的FD 
void set_nonblocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags < 0) {
        perror("fcntl F_GETFL failed");
        return;
    }
    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
        perror("fcntl F_SETFL failed");
    }
}

int main() {
    int server_fd, client_fd, epoll_fd, nfds, i;
    struct sockaddr_in address;
    struct epoll_event ev, events[MAX_EVENTS];
    char buffer[BUFFER_SIZE];

    // 创建并配置服务器socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    set_nonblocking(server_fd);  // 设置为非阻塞模式

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(8080);
    bind(server_fd, (struct sockaddr *)&address, sizeof(address));
    listen(server_fd, 5);

    // 创建epoll实例
    epoll_fd = epoll_create1(0);

    // 将server_fd添加到epoll（边缘触发模式）
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = server_fd;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev);

    printf("Server started (ET mode)...\n");

    // 主循环
    while (1) {
        nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        for (i = 0; i < nfds; i++) {
            // 处理新连接
            if (events[i].data.fd == server_fd) {
                while (1) {  // 循环接受所有连接（边缘触发要求）
                    client_fd = accept(server_fd, NULL, NULL);
                    if (client_fd < 0) {
                        if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                            // 没有更多连接
                            break;
                        }
                        perror("accept failed");
                        break;
                    }
                    set_nonblocking(client_fd);  // 设置为非阻塞模式

                    // 添加到epoll（边缘触发模式）
                    ev.events = EPOLLIN | EPOLLET;
                    ev.data.fd = client_fd;
                    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev);
                }
            }
            // 处理客户端数据
            else {
                client_fd = events[i].data.fd;
                while (1) {  // 循环读取所有数据（边缘触发要求）
                    memset(buffer, 0, BUFFER_SIZE);
                    int bytes_read = read(client_fd, buffer, BUFFER_SIZE);
                    if (bytes_read < 0) {
                        if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                            // 没有更多数据
                            break;
                        }
                        perror("read error");
                        close(client_fd);
                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
                        break;
                    } else if (bytes_read == 0) {
                        // 客户端关闭连接
                        printf("Client disconnected\n");
                        close(client_fd);
                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, NULL);
                        break;
                    } else {
                        // 处理数据
                        printf("Received: %s\n", buffer);
                        // 注意：此处应循环写入所有数据（非阻塞模式）
                        write(client_fd, buffer, bytes_read);
                    }
                }
            }
        }
    }

    close(server_fd);
    close(epoll_fd);
    return 0;
}